package services

import beans.User
import beans.UserInfo
import com.alibaba.fastjson.JSON
import com.jfinal.plugin.activerecord.ActiveRecordException
import com.jfinal.plugin.activerecord.Db
import base.JuHeApi
import base.Message
import base.State
import common.permission.Permission
import common.permission.PermissionManager
import controllers.UserController
import models.UserInfoM
import models.UserM
import utils.CheckSumUtils
import utils.LogUtil
import utils.NetworkUtil
import utils.SafeUtil
import kotlin.random.Random

class UserService(controller: UserController): BaseService<UserController>(controller) {

    companion object{
         val TAG = UserService::class.simpleName!!
    }

    fun registerByPhone(phone: String){
        val user = UserM()
        val tmp = CheckSumUtils.getMD5(phone+System.currentTimeMillis())
        val username = "dy"+tmp.substring(tmp.length-8, tmp.length)
        user[UserM.USERNAME] = username
        //手机注册默认密码为手机号后6位
        user[UserM.PASSWORD] = CheckSumUtils.getSHA1(phone.substring(phone.length-6, phone.length))
        user[UserM.PHONE] = phone
        user[UserM.REGISTER_TIME] = System.currentTimeMillis()
        user[UserM.STATE] = PermissionManager.getUserDefaultPermission()
        try {
            val isSuccess = Db.tx {
                return@tx user.save() && initUserInfo(user.getInt(UserM.ID))
            }
            if (isSuccess){
                val message = Message(State.STATE_SUCCESS, data = User(null, username, "", phone))
                controller.renderJson(message)
            }else{
                val message = Message(State.STATE_USER_REGISTER_FAIL,
                        data = State.getEorrorStr(State.ERROR_UNKNOWN))
                controller.renderJson(message)
            }
        } catch (e: ActiveRecordException){
            LogUtil.i(TAG, e.toString())
            //注册失败可能原因：1. 用户名已存在，重试; 2. 号码已存在; 3. 数据库故障等其他原因
            var message: Message<String>? = null
            if (UserM.findUserByPhone(phone).isNotEmpty()){
                message = Message(State.STATE_USER_REGISTER_FAIL,
                        data = State.getEorrorStr(State.ERROR_USER_PHONE_HAS_SIGNED))
            }
            if (message == null && UserM.findUserByUsername(username).isNotEmpty()){
                message = Message(State.STATE_USER_REGISTER_FAIL,
                        data = State.getEorrorStr(State.ERROR_USER_PHONE_HAS_SIGNED))
            }
            message = message ?: Message(State.STATE_USER_REGISTER_FAIL,
                    data = State.getEorrorStr(State.ERROR_UNKNOWN))
            controller.renderJson(message)
        }

    }

    private fun initUserInfo(userId: Int?): Boolean {
        if (userId == null){
            throw IllegalArgumentException("userId must not be null!")
        }
        val time = System.currentTimeMillis()
        val model = UserInfoM()
        model[UserInfoM.USER_ID] = userId
        model[UserInfoM.NICK_NAME] = "新用户${time%(10*4)}"
        model[UserInfoM.AVATAR] = "/res/avatar/avatar${time%10}"
        return model.save()
    }

    fun loginByPhone(phone: String) {
        val list = UserM.findUserByPhone(phone)
        if (list.isEmpty()){
            val message = Message(State.STATE_USER_LOGIN_FAIL,
                    data = State.getEorrorStr(State.ERROR_USER_PHONE_NOT_SIGNED))
            controller.renderJson(message)
            return
        }
        val userModel = list.first()
        //权限检测
        val state = userModel.getInt(UserM.STATE)
        if (!PermissionManager.checkPermission(state, Permission.LOGIN)){
            val message = Message(State.STATE_USER_LOGIN_FAIL,
                    data = State.getEorrorStr(State.ERROR_USER_NOT_LOGIN_PERMISSION))
            controller.renderJson(message)
            return
        }
        val user = User.formModel(userModel)
        val userInfoModel = UserInfoM.findInfobyUserId(userModel[UserM.ID])
        val userInfo = UserInfo.fromModel(userInfoModel!!)
        val token = SafeUtil.generateToken(userModel[UserM.ID], 60*60*24*15, userModel[UserM.PASSWORD])
        val message = Message(State.STATE_SUCCESS,
                data = hashMapOf("token" to token, "user" to user, "user_info" to userInfo))
        controller.renderJson(message)
    }

    fun getVerifyCode(phone: String): String?{
        val code = getRandomCode()
        val params = hashMapOf<String, String>(
                "mobile" to phone,
                "tpl_id" to JuHeApi.TEMPLATE_ID,
                "key" to UserController.prop.get("jh_app_key"),
                "tpl_value" to NetworkUtil.urlEncode("#code#=$code")
        )
        val response = NetworkUtil.post(JuHeApi.URL_SMS_CDOE, params)
        if (response.code() == 200){
            val result = response.body()?.string()
            val jsonObj = JSON.parseObject(result)
            val error_code = jsonObj["error_code"]
            if (error_code == 0){
                val message = Message(State.STATE_SUCCESS, data = "")
                controller.renderJson(message)
                return code
            }else{
                val message = Message(State.STATE_USER_REQUEST_VERIFY_CODE_FAIL,
                        data = State.getEorrorStr(State.ERROR_SERVER_INSIDE_ERROR))
                LogUtil.i(UserController.TAG, jsonObj["reason"].toString())
                controller.renderJson(message)
            }
        }else {
            val message = Message(State.STATE_USER_REQUEST_VERIFY_CODE_FAIL,
                    data = State.getEorrorStr(State.ERROR_SERVER_INSIDE_ERROR))
            controller.renderJson(message)
        }
        return null
    }

    private fun getRandomCode(): String {
        val random = Random(System.currentTimeMillis()).nextInt(100000, 999999)
        LogUtil.i(TAG, "getRandomCode: random=${random}")
        return random.toString()
    }

    fun updateUserInfo(userId: Int, userInfo: UserInfo) {
        val model = UserInfoM.findInfobyUserId(userId)
        if (model != null){
            userInfo.avatar?.let { model[UserInfoM.AVATAR] = it }
            userInfo.nick_name?.let { model[UserInfoM.NICK_NAME] = it }
            userInfo.sign?.let { model[UserInfoM.SIGN] = it }
            userInfo.sex?.let { model[UserInfoM.SEX] = it }
            userInfo.birthday?.let { model[UserInfoM.BIRTHDAY] = it }
            userInfo.stu_id?.let { model[UserInfoM.STU_ID] = it }
            userInfo.college?.let { model[UserInfoM.COLLEGE] = it }
            userInfo.school?.let { model[UserInfoM.SCHOOL] = it }
            if (model.update()){
                val message = Message(State.STATE_SUCCESS, data = "")
                controller.renderJson(message)
            } else {
                val message = Message(State.STATE_FAIL, data = State.getEorrorStr(State.ERROR_SERVER_INSIDE_ERROR))
                controller.renderJson(message)
            }
        } else {
            val message = Message(State.STATE_FAIL, data = State.getEorrorStr(State.ERROR_USER_USER_NOT_EXIST))
            controller.renderJson(message)
        }
    }

    fun getInfo(userId: Int) {
        val model = UserInfoM.findInfobyUserId(userId)
        if (model != null){
            val info = UserInfo.fromModel(model)
            val message = Message(State.STATE_SUCCESS, data = info)
            controller.renderJson(message)
        } else {
            val message = Message(State.STATE_FAIL, data = State.getEorrorStr(State.ERROR_USER_USER_NOT_EXIST))
            controller.renderJson(message)
        }
    }

    fun findUserInfo(userId: Int) {
        val userM = UserM.AGENT.findById(userId)
        val infoM = UserInfoM.findInfobyUserId(userId)
        if (userM == null){
            val message = Message(State.STATE_FAIL, data = State.getEorrorStr(State.ERROR_USER_USER_NOT_EXIST))
            controller.renderJson(message)
        } else {
            val user = User.formModel(userM)
            val info = UserInfo.fromModel(infoM)
            val map = hashMapOf(
                    "user" to user,
                    "info" to info
            )
            val message = Message(State.STATE_SUCCESS, data = map)
            controller.renderJson(message)
        }
    }

}